package com.errol.generic.http.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.renjia.service.http.HttpLogger;
import com.renjia.service.log.LogService;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.nio.charset.Charset;
import java.util.Map;

/**
 * @author zhang xiao bin
 * @version v1.0
 * @date 2020/10/16
 * @since v
 **/
@Service
public class HttpLoggerImpl implements HttpLogger {

    private final ObjectMapper objectMapper;
    private final LogService logService;

    public HttpLoggerImpl(LogService logService) {
        this.logService = logService;
        objectMapper = new ObjectMapper();
    }

    private String toJsonStr(Object o) {
        try {
            return objectMapper.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            return "jackson serialization exception";
        }
    }

    private String toByteStr(byte[] bytes) {
        return bytes.length > 10240 ? "read bytes length=" + bytes.length : "read bytes to string=" + new String(bytes);
    }

    private String prefix(String url) {
        return "HttpService 调用请求异常：url=" + url;
    }

    @Override
    public void paramException(String url, Map<String, Object> reqParams, Charset charset, Exception exception) {
        logService.error(exception, prefix(url) + ", charset=" + charset + ", reqParams=" + toJsonStr(reqParams));
    }

    @Override
    public void paramException(String url, Object requestData, Map<String, Object> reqParams, Exception exception) {
        logService.error(exception, prefix(url) + ", requestData=" + toJsonStr(requestData) + ", reqParams=" + toJsonStr(reqParams));
    }

    @Override
    public void paramException(String url, byte[] bytes, Exception exception) {
        logService.error(exception, prefix(url) + toByteStr(bytes));
    }

    @Override
    public <T> void paramException(String url, byte[] bytes, Charset charset, TypeReference<T> typeReference, Exception exception) {
        logService.error(exception, prefix(url) + ", resultType=" + typeReference.getType().toString() + ", charset=" + charset + toByteStr(bytes));
    }

    @Override
    public void paramException(String url, byte[] bytes, Charset charset, Class<?> resultType, Exception exception) {
        logService.error(exception, prefix(url) + ", resultType=" + resultType.toString() + ", charset=" + charset + toByteStr(bytes));
    }

    @Override
    public void componentException(String url, Exception exception) {
        logService.error(exception, prefix(url));
    }

    @Override
    public void componentException(String url, String headerKey, String headerValue, Exception exception) {
        logService.error(exception, prefix(url) + ", headerKey=" + headerKey + ", headerValue=" + headerValue);
    }

    @Override
    public void componentException(String url, String bodyDataStr, Charset charset, Exception exception) {
        logService.error(exception, prefix(url) + ",charset=" + charset + ", bodyDataStr=" + bodyDataStr);
    }

    @Override
    public void componentException(String url, boolean responseSuccess, Exception exception) {
        logService.error(exception, prefix(url) + (responseSuccess ? ", response code 200" : ", get response fail"));
    }

    @Override
    public void httpFailed(String url, HttpStatus httpStatus, String response) {
        logService.error(new Exception("http response status=" + httpStatus.toString() + "(" + httpStatus.getReasonPhrase() + ")"),
                prefix(url) + ", response status=" + httpStatus.toString() + "(" + httpStatus.getReasonPhrase() + "), response body=" + response);
    }
}
